package com.chaike.hsq.storage;

import com.chaike.hsq.consts.HsqConsts;
import com.chaike.hsq.exception.HuiShouQianRuntimeException;
import com.chaike.hsq.properties.HuiShouQianProperties;
import com.chaike.hsq.utils.RsaReadUtil;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 内存存储配置缓存实现.
 *
 * @author Luo
 * @version 1.0
 * @date 2021-12-31 10:51:00
 */
public class DefaultConfigStorageImpl implements HsqConfigStorage {

    /**
     * 公私钥.
     */
    private static final ConcurrentMap<String, Object> PUBLIC_PRIVATE_KEY = new ConcurrentHashMap<String, Object>();

    /**
     * 文件上传请求接口.
     */
    private volatile String uploadUrl;

    /**
     * 代理商编号.
     * <pre>
     *     服务端分配商户编号
     * </pre>
     */
    private volatile String agentMerchantNo;

    /**
     * 私钥证书文件路径.
     */
    private volatile String pfxPath;

    /**
     * 私钥密码.
     */
    private volatile String pfxPwd;

    /**
     * 公钥证书文件路径.
     */
    private volatile String cerPath;

    /**
     * 商户配置.
     */
    private volatile HuiShouQianProperties.Merchant merchant;

    /**
     * 支付配置.
     */
    private volatile HuiShouQianProperties.Pay pay;

    public DefaultConfigStorageImpl() {

    }

    public DefaultConfigStorageImpl(final HuiShouQianProperties huiShouQianProperties) {
        this.uploadUrl = huiShouQianProperties.getUploadUrl();
        this.agentMerchantNo = huiShouQianProperties.getAgentMerchantNo();
        this.pfxPath = huiShouQianProperties.getPfxPath();
        this.pfxPwd = huiShouQianProperties.getPfxPwd();
        this.cerPath = huiShouQianProperties.getCerPath();
        this.merchant = huiShouQianProperties.getMerchant();
        this.pay = huiShouQianProperties.getPay();
        // 初始化公私钥
        this.initCert();
    }

    /**
     * 获取文件上传URL.
     *
     * @return 文件上传URL
     */
    @Override
    public String getUploadUrl() {
        return uploadUrl;
    }

    /**
     * 获取代理商编号.
     *
     * @return 代理商编号
     */
    @Override
    public String getAgentMerchantNo() {
        return agentMerchantNo;
    }

    /**
     * 获取私钥证书文件路径.
     *
     * @return 私钥证书文件路径
     */
    @Override
    public String getPfxPath() {
        return pfxPath;
    }

    /**
     * 获取私钥密码.
     *
     * @return 私钥密码
     */
    @Override
    public String getPfxPwd() {
        return pfxPwd;
    }

    /**
     * 获取公钥证书文件路径.
     *
     * @return 公钥证书文件路径
     */
    @Override
    public String getCerPath() {
        return cerPath;
    }

    /**
     * 获取私钥.
     *
     * @return 私钥
     */
    @Override
    public PrivateKey getPrivateKey() {
        if (!PUBLIC_PRIVATE_KEY.containsKey(HsqConsts.PRIVATE_KEY)) {
            throw new HuiShouQianRuntimeException("加载私钥证书失败！");
        }
        return (PrivateKey) PUBLIC_PRIVATE_KEY.get(HsqConsts.PRIVATE_KEY);
    }

    /**
     * 获取公钥.
     *
     * @return 公钥
     */
    @Override
    public PublicKey getPublicKey() {
        if (!PUBLIC_PRIVATE_KEY.containsKey(HsqConsts.PUBLIC_KEY)) {
            throw new HuiShouQianRuntimeException("加载公钥证书失败！");
        }
        return (PublicKey) PUBLIC_PRIVATE_KEY.get(HsqConsts.PUBLIC_KEY);
    }

    /**
     * 获取商户配置.
     *
     * @return 商户配置
     */
    @Override
    public HuiShouQianProperties.Merchant getMerchant() {
        return merchant;
    }

    /**
     * 获取支付配置.
     *
     * @return 支付配置
     */
    @Override
    public HuiShouQianProperties.Pay getPay() {
        return pay;
    }

    /**
     * 初始化公私钥证书.
     */
    private void initCert() {
        // 读取私钥
        PrivateKey privateKey = RsaReadUtil.getPrivateKeyFromFile(pfxPath, pfxPwd);
        if (Objects.isNull(privateKey)) {
            throw new HuiShouQianRuntimeException("加载私钥证书失败！");
        }
        PUBLIC_PRIVATE_KEY.put(HsqConsts.PRIVATE_KEY, privateKey);
        // 读取公钥
        PublicKey publicKey = RsaReadUtil.getPublicKeyFromFile(cerPath);
        if (Objects.isNull(publicKey)) {
            throw new HuiShouQianRuntimeException("加载公钥证书失败！");
        }
        PUBLIC_PRIVATE_KEY.put(HsqConsts.PUBLIC_KEY, publicKey);
    }

}
